package cn.edu.csust.coursecard.service.impl;

import cn.edu.csust.coursecard.dao.dto.*;
import cn.edu.csust.coursecard.dao.entity.Comment;
import cn.edu.csust.coursecard.dao.entity.Post;
import cn.edu.csust.coursecard.dao.entity.Reply;
import cn.edu.csust.coursecard.common.CodeEnum;
import cn.edu.csust.coursecard.dao.CommentMapper;
import cn.edu.csust.coursecard.dao.PostMapper;
import cn.edu.csust.coursecard.dao.entity.StuInfo;
import cn.edu.csust.coursecard.exception.BaseException;
import cn.edu.csust.coursecard.service.ICommentService;
import cn.edu.csust.coursecard.service.StuInfoService;
import cn.edu.csust.coursecard.utils.SensitiveFilter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class CommentServiceImpl implements ICommentService {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(CommentServiceImpl.class);
    
    @Autowired
    private PostMapper postMapper;
    
    @Autowired
    private CommentMapper commentMapper;
    
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    
    @Autowired
    private SensitiveFilter sensitiveFilter;
    
    @Autowired
    private StuInfoService stuInfoService;
    
    
    @Override
    @Transactional
    public CommentInfo writeComment(Comment comment) {
        //参数校验
        if(StringUtils.isEmpty(comment.getContent())){
            throw new BaseException(CodeEnum.PARAM_ERROR.getCode(),"参数错误");
        }
        //判断评论的帖子是否存在;
        Post post = postMapper.selectByPrimaryKey(comment.getPostId());
        if(post == null){
            throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "评论失败");
        }
        comment.setContent(sensitiveFilter.filter(comment.getContent()));
        //补充参数
        Date date = new Date();
        comment.setIsRead(comment.getUserId().equals(post.getUserId())).setIsValid(true).setCreateTime(date).setUpdateTime(date);
        int row = commentMapper.insertComment(comment);
        if(row != 1){
            throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "评论失败");
        }
        try {
            postMapper.updatePostCommentNum(post.getId(),true);
            redisTemplate.delete(RedisKeyConstant.INDEX_POST + post.getId());
        }catch (Exception e){
            throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "评论失败");
        }
        StuInfo stuInfo = stuInfoService.getStuInfoFromDB(comment.getUserId(), comment.getUserId(), null);
        UserInfo userInfo = new UserInfo(stuInfo.getId(), stuInfo.getAvatar(), stuInfo.getUsername());
        return new CommentInfo(comment.getId(),userInfo,comment.getContent(),new ArrayList<>(),comment.getCreateTime());
    }
    
    @Override
    @Transactional
    public ReplyInfo writeReply(Reply reply) {
        //参数校验
        if(StringUtils.isEmpty(reply.getContent())){
            throw new BaseException(CodeEnum.PARAM_ERROR.getCode(),"参数错误");
        }
        Comment result = commentMapper.selectCommentById(reply.getCommentId());
        if(result == null){
            throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "回复失败");
        }
        reply.setContent(sensitiveFilter.filter(reply.getContent()));
        //如果是自己回复自己的评论，或者自己回复自己的回复
        reply.setIsRead(result.getUserId().equals(reply.getUserId()) || reply.getUserId().equals(reply.getReplyId()));
        Date date = new Date();
        reply.setIsValid(true).setCreateTime(date).setUpdateTime(date);
        int row = commentMapper.insertReply(reply);
        if(row != 1){
            throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "回复失败");
        }
        UserInfo userInfo = stuInfoService.getUserInfo(reply.getUserId());
        String replyName = null;
        if(reply.getReplyId() != 0){
            replyName = stuInfoService.getUserInfo(reply.getReplyId()).getUsername();
        }
        return new ReplyInfo(reply.getId(),userInfo,replyName,reply.getCommentId(),reply.getContent(),reply.getCreateTime());
    }
    
    @Override
    public List<CommentInfo> getCommentInfo(Integer postId) {
        List<CommentInfo> commentInfos = commentMapper.selectCommentInfo(postId);
        for (CommentInfo commentInfo : commentInfos) {
            List<ReplyInfo> replyInfos = commentMapper.selectReplyInfo(commentInfo.getId());
            commentInfo.setReplyInfos(replyInfos);
        }
        return commentInfos;
    }
    
    @Override
    @Transactional
    public List<Message> getUnreadMessage(Integer userId) {
        //未读的消息有三种情况：
        //1.该用户发布了帖子，其他用户在帖子下的评论。
        //2.该用户在帖子下面发布了评论，其他人对评论做出了回复
        //3.该用户在评论下面做出了回复，其他人对该回复做出了回复
        
        return getMessage(userId,false);
    }
    
    @Override
    public List<Message> getHasReadMessage(Integer userId) {
    
        return getMessage(userId, true);
    }
    
    private List<Message> getMessage(Integer userId,Boolean isRead){
        //获取帖子中的评论消息,排除自己的评论
        List<Message> messagesFormPost = commentMapper.selectMessageFromPost(userId,isRead);
        //将这些评论设置为已读
//        if(messagesFormPost.size() > 0){
//            List<Integer> commentIds = messagesFormPost.stream().map(Message::getId).collect(Collectors.toList());
//            int rows = commentMapper.setCommentToRead(commentIds);
//            if(rows != commentIds.size()){
//                throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "消息更新失败");
//            }
//        }
        //从评论中获取回复消息,排除自己的评论
        List<Message> messagesFromComment = commentMapper.selectMessageFromComment(userId,isRead);
        //从回复中获取回复消息
        List<Message> messagesFromReply = commentMapper.selectMessageFromReply(userId,isRead);
        messagesFormPost.addAll(messagesFromComment);
        //将这些回复设置为已读
//        if(messagesFromComment.size() >0){
//            List<Integer> replyIds = messagesFromComment.stream().map(Message::getId).collect(Collectors.toList());
//            int rows = commentMapper.setReplyToRead(replyIds);
//            if(rows != replyIds.size()){
//                throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "消息更新失败");
//            }
//        }
        //将所有数据放到一个集合中
        messagesFormPost.addAll(messagesFromReply);
        //按照发布时间进行降序排列
        messagesFormPost.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        return messagesFormPost;
    }
    
    
    
    @Override
    @Transactional
    public void setMessageToRead(Message message) {
        if(message.getType() != 1 && message.getType() != 0){
            throw new BaseException(CodeEnum.PARAM_ERROR.getCode(), "参数错误");
        }
        int rows = commentMapper.setMessageToRead(message);
        if(rows != 1){
            throw new BaseException(CodeEnum.SYSTEM_ERROR.getCode(), "系统错误");
        }
    }
    
    @Override
    @Transactional
    public void setAllMessageToRead(Integer userId) {
          commentMapper.setPostMessageToRead(userId);
          commentMapper.setCommentMessageToRead(userId);
          commentMapper.setReplyMessageToRead(userId);
    }
    
    @Override
    public List<Integer> getCommentIdsByPostId(Integer postId) {
        return commentMapper.selectCommentIdsByPostId(postId);
    }
    
    @Override
    @Transactional
    public void deleteComment(Integer postId,List<Integer> commentIds) {
        if(commentIds != null && commentIds.size() > 0){
            //删除评论
            int row = commentMapper.deleteCommentByIds(commentIds);
            if(row != commentIds.size()){
                throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "删除评论失败");
            }
            //查询评论中的回复
            List<Integer> replyIds = commentMapper.selectReplyByCommentIds(commentIds);
            if(replyIds != null && replyIds.size() >0){
                deleteReply(replyIds);
            }
            postMapper.updatePostCommentNum(postId,false);
        }
        //删除redis中的数据
        List<String> deleteKeys = new ArrayList<>();
        Collections.addAll(deleteKeys,RedisKeyConstant.INDEX_POST+postId,RedisKeyConstant.LIKE_NUM+postId,RedisKeyConstant.LIKE_POST+postId);
        redisTemplate.delete(deleteKeys);
    }
    
    @Override
    @Transactional
    public void deleteReply(List<Integer> replyIds) {
         int row = commentMapper.deleteReplyByIds(replyIds);
         if(row != replyIds.size()){
             throw new BaseException(CodeEnum.REQUEST_FAILED.getCode(), "删除回复失败");
         }
    }
    
    @Override
    public Comment getCommentByPrimaryKey(Integer commentId) {
        return commentMapper.selectCommentById(commentId);
    }
    
    @Override
    public Reply getReplyByPrimaryKey(Integer replyId) {
        return commentMapper.selectReplyById(replyId);
    }
}
